package guichatapplication;

import chatclient.ChatClient;
import chatclient.IOnDisconnectListener;
import chatclient.IOnGroupListener;
import chatclient.IOnLoginListener;
import chatclient.IOnRegistryListener;
import chatclient.IOnTransferListener;
import java.awt.Desktop;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JList;
import javax.swing.JOptionPane;

public class MainWindow extends javax.swing.JFrame implements IOnTransferListener, IOnRegistryListener, IOnLoginListener, IOnDisconnectListener, IOnGroupListener {

    private HashMap<String, IndividualWindow> windows = new HashMap<>();
    private ArrayList<CustomListCell> lstClients = new ArrayList<>();

    @SuppressWarnings("empty-statement")
    public MainWindow() {
        initComponents();
        
        /*
        this.lstClients.add(new CustomListCell("ds1"));
        this.lstClients.add(new CustomListCell("ds2"));
        this.lstClients.add(new CustomListCell("ds3"));
        * */
        
        this.listFriend.setCellRenderer(new ListFriendCellRender());
        this.resetJListModel();
        jScrollPane1.setViewportView(listFriend);
        listFriend.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent evt) {
                JList list = (JList) evt.getSource();
                if (evt.getClickCount() == 2) {
                    int index = list.locationToIndex(evt.getPoint());
                    CustomListCell element = (CustomListCell) list.getSelectedValue();
                    IndividualWindow newWindow = windows.get(element.getIdentify());
                    if (newWindow == null) {                       
                        if(element.getIdentifies()!=null) {
                            ArrayList<String> lstFriendOutGroup = new ArrayList<>();
                            String thisUsername = ChatClient.getInstance().getUsername();
                            for (CustomListCell customListCell : lstClients) {
                                if (customListCell.isGroup() == false) {
                                    if (!element.getIdentifies().contains(customListCell.getIdentify())) {
                                        lstFriendOutGroup.add(customListCell.getIdentify());
                                    }
                                }
                            }
                            newWindow = new IndividualWindow(element.getIdentify(), element.getIdentifies(), lstFriendOutGroup);
                        }
                        else
                            newWindow = new IndividualWindow(element.getIdentify());
                        
                        windows.put(element.getIdentify(), newWindow);
                    }
                    newWindow.setVisible(true);
                    newWindow.addMessage(element.getMessage());
                    element.deleteMessage();

                    // set CustomListCell to normal icon, not new message icon
                    element.setNormal();
                }
            }
        });        
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        label1 = new java.awt.Label();
        label2 = new java.awt.Label();
        tbUserName = new javax.swing.JTextField();
        btnConnect = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        listFriend = new javax.swing.JList();
        jButton1 = new javax.swing.JButton();
        tbGroupName = new javax.swing.JTextField();
        btnCreateGroup = new javax.swing.JButton();
        tbPassword = new javax.swing.JPasswordField();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        label1.setText("User Name");

        label2.setText("Password");

        tbUserName.setName(""); // NOI18N

        btnConnect.setText("Log In");
        btnConnect.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btnConnectMouseClicked(evt);
            }
        });

        jScrollPane1.setViewportView(listFriend);

        jButton1.setText("Register");
        jButton1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButton1MouseClicked(evt);
            }
        });

        btnCreateGroup.setText("Create Group");
        btnCreateGroup.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCreateGroupActionPerformed(evt);
            }
        });

        tbPassword.setToolTipText("");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(label1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(1, 1, 1)
                        .addComponent(tbUserName))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(label2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(tbPassword)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(btnConnect)
                    .addComponent(jButton1)))
            .addGroup(layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 165, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(tbGroupName)
                    .addComponent(btnCreateGroup, javax.swing.GroupLayout.DEFAULT_SIZE, 120, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(label1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(tbUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(jButton1)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(label2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnConnect)
                    .addComponent(tbPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 266, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(tbGroupName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnCreateGroup)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );

        btnConnect.getAccessibleContext().setAccessibleName("");

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnConnectMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnConnectMouseClicked

        String userName = this.tbUserName.getText();
        String password = this.tbPassword.getText();
        if (userName.isEmpty() || password.isEmpty()) {
            JOptionPane.showMessageDialog(null, "Fill UserName/Password", "InfoBox: " + "Validation", JOptionPane.INFORMATION_MESSAGE);
            return;
        }

        ChatClient.getInstance().login(userName, password);
        //this.network.login(userName, password);
    }//GEN-LAST:event_btnConnectMouseClicked

    private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jButton1MouseClicked
        String userName = this.tbUserName.getText();
        String password = this.tbPassword.getText();
        //this.network.registry(userName, password);
        ChatClient.getInstance().registry(userName, password);
    }//GEN-LAST:event_jButton1MouseClicked

    private void btnCreateGroupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCreateGroupActionPerformed

        this.isCreateGroupFlag=true;
        List<CustomListCell> lst = this.listFriend.getSelectedValuesList();
        if (lst.size() < 2) {
            JOptionPane.showMessageDialog(null, "Choose at least 2 Friends to make group", "InfoBox: " + "Validation", JOptionPane.INFORMATION_MESSAGE);
        }

        String[] lstIdentifies = new String[lst.size()];

        int i = 0;
        for (CustomListCell client : lst) {
            lstIdentifies[i] = client.getIdentify();
            ++i;
        }

        ChatClient.getInstance().createGroup(lstIdentifies);
    }//GEN-LAST:event_btnCreateGroupActionPerformed

    private void resetJListModel() {
        listFriend.setModel(new javax.swing.AbstractListModel() {
            @Override
            public int getSize() {
                return lstClients.size();
            }

            @Override
            public Object getElementAt(int i) {
                return lstClients.get(i);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnConnect;
    private javax.swing.JButton btnCreateGroup;
    private javax.swing.JButton jButton1;
    private javax.swing.JScrollPane jScrollPane1;
    private java.awt.Label label1;
    private java.awt.Label label2;
    private javax.swing.JList listFriend;
    private javax.swing.JTextField tbGroupName;
    private javax.swing.JPasswordField tbPassword;
    private javax.swing.JTextField tbUserName;
    // End of variables declaration//GEN-END:variables
    
    @Override
    public void onNewMessage(String sender, String message) {
        int i;
        for (i = 0; i < this.lstClients.size(); i++) {
            CustomListCell obj = this.lstClients.get(i);
            if (obj.getIdentify().equals(sender)) {
                obj.setUnreadMessage();
                //obj.addMessage(message);
                IndividualWindow window = (IndividualWindow) windows.get(sender);
                if (window != null) {
                    window.addMessage(sender + ": " + message);
                } else {
                    obj.addMessage(sender + ": " + message);
                }

                // reset JList
                this.resetJListModel();
                break;
            }
        }
    }

    @Override
    public void onRegistryFailed(String message) {
        JOptionPane.showMessageDialog(null, "Registry Fail, Your user or your password is invalid", "InfoBox: " + "Validation", JOptionPane.INFORMATION_MESSAGE);
    }

    @Override
    public void onRegistrySuccess(String message) {
        JOptionPane.showMessageDialog(null, "Registry Success!, Your user or your password is invalid", "InfoBox: " + "Validation", JOptionPane.INFORMATION_MESSAGE);
        this.resetJListModel();
    }

    @Override
    public void onLoginFailed(String message) {
        JOptionPane.showMessageDialog(null, "Login Fail, Your user or your password is invalid", "InfoBox: " + "Validation", JOptionPane.INFORMATION_MESSAGE);
    }

    @Override
    public void onLoginSuccess(ArrayList<String> listUsers, HashMap<String, ArrayList<String>> listUnreadMessages) {
//        JOptionPane.showMessageDialog(null, "Login Success!", "InfoBox: " + "Validation", JOptionPane.INFORMATION_MESSAGE);
        for (String str : listUsers) {
            this.lstClients.add(new CustomListCell(str));
        }
        
        String[] tmpStr;
        if (listUnreadMessages.size() > 0) {
            for (Map.Entry<String, ArrayList<String>> entry : listUnreadMessages.entrySet()) {
                String name = entry.getKey();
                ArrayList<String> arrayList = entry.getValue();
                for (String message : arrayList) {
                    this.onNewMessage(name, message);
                }
            }
        }
        
        this.resetJListModel();
    }

    @Override
    public void onHasNewUser(String newUsername) {
        this.lstClients.add(new CustomListCell(newUsername));
        this.resetJListModel();
    }

    @Override
    public void onDisconnect() {
        System.out.println("Eu khi nao xai ham nay!");
    }

    boolean isCreateGroupFlag=false;
    
    @Override
    public void onCreateGroupSuccess(String groupId, String[] lstIdentities) {
        CustomListCell cus = new CustomListCell(groupId, lstIdentities);
        this.lstClients.add(cus);
        this.resetJListModel(); 
        if(isCreateGroupFlag)
            JOptionPane.showMessageDialog(null, "Create Group Success", "InfoBox: " + "Validation", JOptionPane.INFORMATION_MESSAGE);        
        isCreateGroupFlag=false;
    }

    @Override
    public void onAddNewUserToGroup(String groupId, String sender, String username, String[] listOldIdentifies) {
        boolean flag = false;
        for (CustomListCell cell : this.lstClients) {
            if (cell.getIdentify().equals(groupId)) {
                cell.getIdentifies().add(username);
                flag = true;
                break;
            }
        }
        
        if (flag == false) { // new user
            CustomListCell cus = new CustomListCell(groupId, listOldIdentifies);
            this.lstClients.add(cus);
        }
        this.resetJListModel();
    }

    @Override
    public void onUserLeaveFromGroup(String groupId, String username) {
        for (CustomListCell cus : this.lstClients) {
            if (cus.getIdentify().equals(groupId)) {
                cus.removeIdentify(username);
            }
        }
        this.resetJListModel();
    }
    
    @Override
    public void onUserRemoveFromGroup(String groupId, String sender, String username) {
        String thisUsername = ChatClient.getInstance().getUsername();
        //CustomListCell tmpCus = null;
        for (CustomListCell cus : this.lstClients) {
            if (cus.getIdentify().equals(groupId)) {
                if (thisUsername.equals(username)) {
                    //tmpCus = cus;
                    this.lstClients.remove(cus);
                } else {
                    cus.removeIdentify(username);
                }
                break;
            }
        }
        this.resetJListModel();
    }

    @Override
    public void onGroupNewMessage(String sender, String groupId, String message) {
        int i;
        for (i = 0; i < this.lstClients.size(); i++) {
            CustomListCell obj = this.lstClients.get(i);
            if (obj.getIdentify().equals(groupId)) {
                obj.setUnreadMessage();
                //obj.addMessage(sender + ": " + message);
                IndividualWindow window = (IndividualWindow) windows.get(groupId);
                if (window != null ) {
                    window.addMessage(sender + ": " + message);
                } else {
                    obj.addMessage(sender + ": " + message);
                }
                // reset JList
                this.resetJListModel();
                break;
            }
        }
    }

    @Override
    public String onNewSendFileSignal(String sender, String fileName) {
        int dialogButton = JOptionPane.YES_NO_OPTION;
        
        String shortFileName= new File(fileName).getName();
        
        int dialogResult = JOptionPane.showConfirmDialog(null, sender + " is sending you a file name: " + shortFileName + "\r\n Do you want to save this file?", "Save File...", dialogButton);
        if (dialogResult == JOptionPane.YES_OPTION) {
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setSelectedFile(new File(shortFileName));
            fileChooser.showSaveDialog(this);
            return fileChooser.getSelectedFile().getPath();
        }
        return ""; // khong gui
    }

    @Override
    public void onSendFileSuccess(String sender, String fileName) {        
        int dialogButton = JOptionPane.YES_NO_OPTION;
        int dialogResult = JOptionPane.showConfirmDialog(null, "Do you want to open file?", "Sent file complete!", dialogButton);
        if (dialogResult == JOptionPane.YES_OPTION) {
            try {
                File file=new File(fileName);
                Desktop.getDesktop().open(new File(file.getParent()));
            } catch (IOException ex) {
                Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    public void onSendMessage(String message) {        
    }
}
